package easier.app.x.view;

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Parcel;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.MaskFilterSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ScaleXSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import androidx.core.content.res.ResourcesCompat;

/**
 * 辅助工具类,构建spannable:
 * 1.图文混排
 * 2.不同文字大小拼接
 * 3.不同文字颜色拼接
 * 4.文字增加点击事件
 * <p>
 * 使用{@link #append(CharSequence)}链接需要处理的字符串,之后调用各种set方法设置需要的样式之后继续拼接{@link #append(CharSequence)}
 * set方法只对当前的拼接的字符串起作用,最后使用{@link #apply()}获取所有字符串
 */
public class SpanTextBuilder {

    private final SpannableStringBuilder mBuilder = new SpannableStringBuilder();//拼接所有编辑
    private SpannableString mEdit = new SpannableString( "" );//当前编辑

    public SpanTextBuilder() {

    }

    public SpanTextBuilder append( CharSequence source ) {

        if ( mEdit != null ) {
            mBuilder.append( mEdit );
        }
        mEdit = new SpannableString( source );
        return this;
    }

    public SpanTextBuilder setForegroundColor( @ColorInt int color ) {

        mEdit.setSpan( new ForegroundColorSpan( color ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder setBackgroundColor( @ColorInt int color ) {

        mEdit.setSpan( new BackgroundColorSpan( color ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder setClickable( ClickableSpan clickable ) {

        mEdit.setSpan( clickable, 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder setTextAppearance( Context context, @StyleRes int style ) {

        mEdit.setSpan( new TextAppearanceSpan( context, style ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder setURLSpan( String url ) {

        mEdit.setSpan( new URLSpan( url ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder setURLColorSpan( TextView textView, String url, @ColorInt int color ) {

        mEdit.setSpan( new UrlColorSpan( textView, url, color ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //设置字体
    public SpanTextBuilder setTypeface( String typeface ) {

        mEdit.setSpan( new TypefaceSpan( typeface ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //下标
    public SpanTextBuilder setSubscript() {

        mEdit.setSpan( new SubscriptSpan(), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //上标
    public SpanTextBuilder setSuperscript() {

        mEdit.setSpan( new SuperscriptSpan(), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //基于X的缩放
    public SpanTextBuilder setScaleX( float proportion ) {

        mEdit.setSpan( new ScaleXSpan( proportion ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //设置的是相对大小
    public SpanTextBuilder setRelativeSize( float size ) {

        mEdit.setSpan( new RelativeSizeSpan( size ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //设置的是绝对大小
    public SpanTextBuilder setAbsoluteSize( int size ) {

        mEdit.setSpan( new AbsoluteSizeSpan( size ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }


    public SpanTextBuilder setStyleSpan( int style ) {

        mEdit.setSpan( new StyleSpan( style ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }


    //粗体斜体
    public SpanTextBuilder setBoldItalic() {

        return setStyleSpan( Typeface.BOLD_ITALIC );
    }

    //粗体
    public SpanTextBuilder setBold() {

        return setStyleSpan( Typeface.BOLD );
    }

    //斜体
    public SpanTextBuilder setItalic() {

        return setStyleSpan( Typeface.ITALIC );
    }

    //正常
    public SpanTextBuilder setNormal() {

        return setStyleSpan( Typeface.NORMAL );
    }

    //删除线
    public SpanTextBuilder setStrikethrough() {

        mEdit.setSpan( new StrikethroughSpan(), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    //下划线
    public SpanTextBuilder setUnderline() {

        mEdit.setSpan( new UnderlineSpan(), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public SpanTextBuilder appendImage( Context context, @DrawableRes int drawableRes ) {

        Drawable drawable = null;
        if ( VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP ) {
            drawable = context.getResources().getDrawable( drawableRes, context.getTheme() );
        } else {
            drawable = context.getResources().getDrawable( drawableRes );
        }
        appendImage( drawable, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight() );
        return this;
    }

    public SpanTextBuilder appendImage( Context context, @DrawableRes int drawableRes, int width, int height ) {

        Drawable drawable = null;
        drawable = ResourcesCompat.getDrawable( context.getResources(), drawableRes, context.getTheme() );
        if ( drawable != null ) {
            return appendImage( drawable, width, height );
        }
        return this;
    }

    public SpanTextBuilder appendImage( Drawable drawable, int width, int height ) {

        append( " " );
        drawable.setBounds( 0, 0, width, height );
        mEdit.setSpan( new ImageSpan( drawable ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }


    //模糊效果.需要关闭硬件加速{android:hardwareAccelerated="false"}
    public SpanTextBuilder setBlurMaskFilter( float radius, BlurMaskFilter.Blur style ) {

        BlurMaskFilter filter = new BlurMaskFilter( radius, style );
        mEdit.setSpan( new MaskFilterSpan( filter ), 0, mEdit.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE );
        return this;
    }

    public CharSequence apply() {

        append( "" );
        return mBuilder;
    }

    /**
     * 可点击span,可设置颜色
     * 可以通过设置{@link TextView#setHighlightColor(int)}为透明取消背景色
     */
    public static abstract class TextViewColorClickSpan extends ClickableSpan {

        @ColorInt
        private final int mColor;

        public TextViewColorClickSpan( TextView textView ) {

            this( textView, textView.getCurrentTextColor() );
        }


        public TextViewColorClickSpan( TextView textView, @ColorInt int color ) {

            mColor = color;
            textView.setMovementMethod( LinkMovementMethod.getInstance() );
        }

        @Override
        public void updateDrawState( @NonNull TextPaint ds ) {

            super.updateDrawState( ds );
            ds.setColor( mColor );
            ds.setUnderlineText( false );
        }
    }

    public static class UrlColorSpan extends URLSpan {

        @ColorInt
        private final int mColor;

        public UrlColorSpan( TextView textView, String url, @ColorInt int color ) {

            super( url );
            mColor = color;
            textView.setMovementMethod( LinkMovementMethod.getInstance() );
        }

        public UrlColorSpan( TextView textView, @NonNull Parcel src, @ColorInt int color ) {

            super( src );

            mColor = color;
            textView.setMovementMethod( LinkMovementMethod.getInstance() );
        }

        @Override
        public void updateDrawState( @NonNull TextPaint ds ) {

            super.updateDrawState( ds );
            ds.setColor( mColor );
            ds.setUnderlineText( false );
        }
    }
}

